package com.example.spider.cluster.common.task;

import com.example.spider.cluster.common.dto.SpiderResultDTO;
import com.example.spider.common.task.ClassUtil;
import com.example.spider.common.task.SpiderTask;
import com.example.spider.common.util.JsonUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * @author lym
 */
@Slf4j
public class SpiderTaskTypeManager {

    private static Map<String, Class<? extends SpiderTask>> spiderTaskTypeMap = new HashMap<>();

    public static void scanSpiderTaskPackage(String... packagePath){
        List<Class<? extends SpiderTask>> spiderTasks = new LinkedList<>();
        for (String p : packagePath) {
            spiderTasks.addAll(ClassUtil.getAllSonOfClass(p, SpiderTask.class));
        }
        addToSpiderMap(spiderTasks);
    }

    public static void addToSpiderMap(List<Class<? extends SpiderTask>> spiderTasks) {
        spiderTasks.forEach(spiderTaskClass -> {
            try {
                SpiderTask task = spiderTaskClass.getDeclaredConstructor().newInstance();
                String type = task.getType();
                spiderTaskTypeMap.put(type, spiderTaskClass);
            } catch (Exception e) {
                log.warn("use default construct instance error: " + spiderTaskClass.getTypeName(), e);
            }
        });
    }

    @Nullable
    public static Class<? extends SpiderTask> getClassByType(String type){
        return spiderTaskTypeMap.get(type);
    }

    @NonNull
    public static Class<? extends SpiderTask> getClassByTypeOrException(String type){
        Class<? extends SpiderTask> clazz = getClassByType(type);
        if(clazz == null){
            throw new IllegalArgumentException("not support such type:" + type);
        }
        return clazz;
    }

    @SuppressWarnings("unchecked")
    public static <T extends SpiderTask> T toSpiderTask(String json, String type) {
        Class<T> clazz = (Class<T>) getClassByTypeOrException(type);
        return JsonUtils.toObject(json, clazz);

    }

    @SuppressWarnings("unchecked")
    public static <T extends SpiderTask> SpiderResultDTO<T> toSpiderResultDTO(String json, String type) {
        Class<? extends SpiderTask> clazz = getClassByTypeOrException(type);
        return JsonUtils.toObject(json, SpiderResultDTO.class, clazz);

    }

}
